﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using WSMX_Invoice;
using WSMX_Invoice.MX;
using WSMX_Invoice.MX.PayRoll;
using WSMX_Invoice.MX.Invoice.Version32;
using WSMX_Invoice.MX.Providers;

namespace WSMX_Libreria_CFDI
{
    class Program
    {
        public const string endpoint = "https://pruebastfd.tralix.com:7070"; // Url del WebService de Pruebas o produccion del proveedor
        public const string customerkey = "8af953a3ba75aa71d71dd45c36c9539689b6cd73"; // Token dado por el proveedor al contratar el servicio
        public const string pathCertificado = @"C:\Test\Cer_Sellos\aaa010101aaa_csd_01.cer"; // Ubicacion del Certificado
        public const string NoCertificado = "00000000000000010101"; // No del Cerficado de Sellos (CSD)        
        public const string filepathXML = @"C:\Test\recibotest.xml"; // Archivo XML resultado
        public const string pathRutaSello = @"C:\Test\Cer_Sellos\aaa010101aaa_csd_01.key"; // Ubicacion del certificado de Sellos (CSD)
        public const string passwordSello = "a0123456789"; // Password del certificado de SELLOS
        public const TypeProviders proveedor = TypeProviders.Tralix; // Enumeracion de proveedor

        static void Main(string[] args)
        {

            Console.WriteLine("Seleccione la opcion deseada: ");
            Console.WriteLine("1.- Timbrado de Comprobante Fiscal. ");
            Console.WriteLine("2.- Timbrado de Nomina. ");
            Console.WriteLine("3.- Validacion Comprobante fiscal. ");
            Console.WriteLine("4.- Cancelacion de Comprobante fiscal. \n");
            Console.WriteLine("Opcion:");

            string op = Console.ReadKey().KeyChar.ToString();

            switch (op)
            {
                case "1": TimbraFactura();  
                    break;
                case "2": TimbraNomina();
                    break;
                case "3": ValidaComprobante();  
                    break;
                case "4": CancelaComprobante();  
                    break;
                default: Console.WriteLine("\n No es una opcion valida"); 
                    break;

            }

            Console.ReadKey();
        }

        private static void CancelaComprobante()
        {
            Console.WriteLine("\n No se ha creado el ejemplo. ");
        }

        private static void ValidaComprobante()
        {
            Console.WriteLine("\n No se ha creado el ejemplo. ");
        }

        private static void TimbraFactura()
        {
            Console.WriteLine("\n No se ha creado el ejemplo. ");
        }

        private static void TimbraNomina()
        {
            Console.WriteLine("\n Iniciando Timbrado Nomina");            

            // Creacion del comprobante
            Comprobante recibo = new Comprobante();
            recibo.Emisor = new ComprobanteEmisor();

            // Inserccion del Emisor
            recibo.Emisor.nombre = "Compañia Prueba  S.A. de C.V.";
            recibo.Emisor.rfc = "AAAA010101AAA";
            recibo.Emisor.DomicilioFiscal = new t_UbicacionFiscal();
            recibo.Emisor.DomicilioFiscal.pais = "Mexico";
            recibo.Emisor.DomicilioFiscal.estado = "Estado de Mexico";
            recibo.Emisor.DomicilioFiscal.municipio = "Tlalnepantla de Baz";
            recibo.Emisor.DomicilioFiscal.colonia = "Tlalnepantla de Baz";
            recibo.Emisor.DomicilioFiscal.calle = "calle prueba";
            recibo.Emisor.DomicilioFiscal.noExterior = "61";
            recibo.Emisor.DomicilioFiscal.noInterior = "1";
            recibo.Emisor.DomicilioFiscal.codigoPostal = "54170";
            recibo.Emisor.ExpedidoEn = new t_Ubicacion();
            recibo.Emisor.ExpedidoEn.pais = "Mexico";
            recibo.Emisor.ExpedidoEn.estado = "Estado de Mexico";
            recibo.Emisor.ExpedidoEn.municipio = "Tlalnepantla de Baz";
            recibo.Emisor.ExpedidoEn.colonia = "Tlalnepantla de Baz";
            recibo.Emisor.ExpedidoEn.calle = "calle prueba";
            recibo.Emisor.ExpedidoEn.noExterior = "61";
            recibo.Emisor.ExpedidoEn.noInterior = "1";
            recibo.Emisor.ExpedidoEn.codigoPostal = "54170";
            recibo.Emisor.RegimenFiscal = new List<ComprobanteEmisorRegimenFiscal>();
            ComprobanteEmisorRegimenFiscal regimen = new ComprobanteEmisorRegimenFiscal();
            regimen.Regimen = "1";
            recibo.Emisor.RegimenFiscal.Add(regimen);

            // Inserccion de los datos del Receptor
            recibo.Receptor = new ComprobanteReceptor();
            recibo.Receptor.nombre = "Sujeto prueba";
            recibo.Receptor.rfc = "COFG670227BC2";
            recibo.Receptor.Domicilio = new t_Ubicacion();
            recibo.Receptor.Domicilio.pais = "Mexico";
            recibo.Receptor.Domicilio.estado = "Estado de Mexico";
            recibo.Receptor.Domicilio.municipio = "Tlalnepantla de Baz";
            recibo.Receptor.Domicilio.colonia = "Tlalnepantla de Baz";
            recibo.Receptor.Domicilio.calle = "Calle prueba";
            recibo.Receptor.Domicilio.noExterior = "61";
            recibo.Receptor.Domicilio.noInterior = "1";
            recibo.Receptor.Domicilio.codigoPostal = "54170";

            // Insersion de los datos del complemento de Nomina
            recibo.Complemento = new ComprobanteComplemento();

            Nomina nomina = new Nomina();
            nomina.FechaPago = recibo.fecha;
            nomina.Antiguedad = 1;
            nomina.Banco = 14;
            nomina.CLABE = "123456789012345678";
            nomina.CURP = "COFG600227MDFRRR08";
            nomina.Departamento = "SUCURSAL";
            nomina.FechaFinalPago = nomina.FechaPago;
            nomina.FechaInicialPago = nomina.FechaPago;
            nomina.NumDiasPagados = 7;
            nomina.NumEmpleado = "4";
            nomina.NumSeguridadSocial = "28136000156";
            nomina.PeriodicidadPago = "SEMANAL";
            nomina.Puesto = "AUXILIAR DE COCINA B";
            nomina.RegistroPatronal = "Y5652091108";
            nomina.RiesgoPuesto = 1;
            nomina.SalarioDiarioIntegrado = decimal.Parse("108.00");
            nomina.SalarioBaseCotApor = nomina.SalarioDiarioIntegrado; //******************Revisar con su asesor Fiscal
            nomina.TipoContrato = "LABORAL"; //***************************** Revisar los tipos de contratos vigentes
            nomina.TipoJornada = "Diurno";
            nomina.TipoRegimen = 1;

            //nomina.Horas Extras            
            nomina.HorasExtras = new List<WSMX_Invoice.MX.PayRoll.NominaHorasExtra>();
            WSMX_Invoice.MX.PayRoll.NominaHorasExtra horasExtras = new WSMX_Invoice.MX.PayRoll.NominaHorasExtra();
            horasExtras.Dias = 1;
            horasExtras.HorasExtra = 1;
            horasExtras.ImportePagado = 10;
            horasExtras.TipoHoras = WSMX_Invoice.MX.PayRoll.NominaHorasExtraTipoHoras.Dobles;
            nomina.HorasExtras.Add(horasExtras);
            
            // Listado de Deducciones, Revisar con su asesor fiscal
            nomina.Deducciones.Deduccion = new List<WSMX_Invoice.MX.PayRoll.NominaDeduccionesDeduccion>();
            WSMX_Invoice.MX.PayRoll.NominaDeduccionesDeduccion deduccion = new WSMX_Invoice.MX.PayRoll.NominaDeduccionesDeduccion();
            deduccion.Clave = "001";
            deduccion.Concepto = "Seguridad social";
            deduccion.TipoDeduccion = 1;
            deduccion.ImporteExento = decimal.Parse("10.02");
            deduccion.ImporteGravado = 0;
            nomina.Deducciones.Deduccion.Add(deduccion);
            nomina.Deducciones.TotalExento = nomina.Deducciones.Deduccion.Sum(x => x.ImporteExento);
            nomina.Deducciones.TotalGravado = nomina.Deducciones.Deduccion.Sum(x => x.ImporteGravado);

            // Listado de Prercepciones, Revisar con sus asesor Fiscal
            nomina.Percepciones.Percepcion = new List<NominaPercepcionesPercepcion>();
            NominaPercepcionesPercepcion percepcion = new WSMX_Invoice.MX.PayRoll.NominaPercepcionesPercepcion();
            percepcion.Clave = "001";
            percepcion.Concepto = "Sueldos, Salarios  Rayas y Jornales";
            percepcion.ImporteExento = decimal.Parse("723.31");
            percepcion.ImporteGravado = 0;
            percepcion.TipoPercepcion = 1;
            nomina.Percepciones.Percepcion.Add(percepcion);
            nomina.Percepciones.TotalExento = nomina.Percepciones.Percepcion.Sum(x => x.ImporteExento);
            nomina.Percepciones.TotalGravado = nomina.Percepciones.Percepcion.Sum(x => x.ImporteGravado);

            // Agrega el complemento de Nomina
            recibo.Complemento.Any.Add(FunctionsXML.GetRootElement(nomina.Serialize()));
            
            // Agrega el concepto del Comprobante Fiscal Digital
            ComprobanteConcepto concepto = new ComprobanteConcepto();
            concepto.cantidad = 1;
            concepto.noIdentificacion = "SMA0001-00003-Normal";
            concepto.importe = nomina.Percepciones.TotalGravado + nomina.Percepciones.TotalExento - nomina.Deducciones.TotalExento - nomina.Deducciones.TotalGravado;
            concepto.unidad = "1";
            concepto.valorUnitario = concepto.importe / concepto.cantidad;
            concepto.descripcion = "Recibo de Nomina";
            recibo.Conceptos.Add(concepto);            

            // Agrega las retenciones de Impuestos, Revisar con su asesor Fiscal
            recibo.Impuestos = new ComprobanteImpuestos(); 
            ComprobanteImpuestosRetencion retencion = new ComprobanteImpuestosRetencion();
            retencion.importe = 20;
            retencion.impuesto = ComprobanteImpuestosRetencionImpuesto.ISR;
            recibo.Impuestos.Retenciones.Add(retencion);            
            recibo.Impuestos.totalImpuestosRetenidos = recibo.Impuestos.Retenciones.Sum(x => x.importe);
            recibo.Impuestos.totalImpuestosTrasladados = recibo.Impuestos.Traslados.Sum(x => x.importe);

            // Finaliza los totales y ultimos parametros del comprobante
            recibo.total = recibo.Conceptos.Sum(x => x.importe);
            recibo.subTotal = recibo.Conceptos.Sum(x => x.importe);
            recibo.formaDePago = "";
            recibo.LugarExpedicion = "calle prueba no. 61-1, col. Prado Vallejo, Tlalnepantla, Edo. de México, México";
            recibo.metodoDePago = "Deposito";
            recibo.Moneda = "MXN";
            recibo.TipoCambio = "1.0";
            recibo.tipoDeComprobante = ComprobanteTipoDeComprobante.egreso;
            recibo.fecha = DateTime.Today;

            // Guarda el certificado en 64 bits
            recibo.certificado = Functions.getFile64(pathCertificado);
            recibo.noCertificado = NoCertificado;

            // Guarda el XML en la ruta especificada
            recibo.SaveToFile(filepathXML);
            // Obtiene la Cadena Original del Comprobante
            string cadena = FunctionsTimbrado.GeneradorCadenas(filepathXML);
            // Genera el Sello del Comprobante
            recibo.sello = FunctionsTimbrado.getSello(pathRutaSello, passwordSello, cadena);
            // Guarda el Archivo en la ruta especificada
            recibo.SaveToFile(filepathXML);

            // Inicializa la clase del timbrado con el proveedor seleccionado
            Provider prov = ProviderFactory.getProvider(proveedor);
            // Inicializa los parametros del proveedor
            prov.setParams_Timbrado(customerkey, endpoint);
            // Timbra el recibo
            if (prov.Timbra(filepathXML))
            {
                Console.WriteLine("Se timbro el recibo correctamente.");
            }
            else
            {
                Console.WriteLine("Error al timbrar el recibo: " + prov.getError());
            }
            
        }
    }
}
